﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Threading;
using Microsoft.Win32;
using MB = System.Windows.MessageBox;

namespace MvvmOrm.Services
{
    public enum DialogResponse { Ok, Yes, No, Cancel }
    public class Dialogs
    {
        Dispatcher _dispatcher;

        public Dialogs()
        {
            _dispatcher = Dispatcher.CurrentDispatcher;
        }
        
        bool IsSynchronized()
        {
            return this._dispatcher.Thread == Thread.CurrentThread;
        }

        void Show(Action action)
        {
            if (IsSynchronized() || _dispatcher == null)
                action();
            else
                _dispatcher.Invoke(action, null);
        }

        public void ShowError(string error_message)
        {
            Action action = () => MB.Show("ERROR: " + error_message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
            Show(action);
        }

        public DialogResponse AskQuestion(string question_message)
        {
            return AskQuestion(question_message, "", false);
        }

        public DialogResponse AskQuestion(string question_message, string caption)
        {
            return AskQuestion(question_message, caption, false);
        }

        public DialogResponse AskQuestion(string question_message, string caption, bool allow_cancel)
        {
            return AskQuestion(question_message, caption, allow_cancel, false);
        }

        public DialogResponse AskQuestion(string question_message, string caption, bool allow_cancel, bool show_as_error)
        {
            MessageBoxResult result = 0;

            Action action = () => result = MB.Show(question_message,
                "",
                allow_cancel ? MessageBoxButton.YesNoCancel : MessageBoxButton.YesNo,
                show_as_error ? MessageBoxImage.Error : MessageBoxImage.Question,
                MessageBoxResult.No);

            Show(action);

            switch (result) {
            case MessageBoxResult.OK:
                return DialogResponse.Ok;
            case MessageBoxResult.Yes:
                return DialogResponse.Yes;
            case MessageBoxResult.No:
                return DialogResponse.No;
            default:
                return DialogResponse.Cancel;
            }
        }

        public void ShowWarning(string message, string caption = "")
        {
            Action action = () => MB.Show("WARNING: " + message, caption, MessageBoxButton.OK, MessageBoxImage.Warning);
            Show(action);
        }

        public void ShowInformation(string message)
        {
            ShowInformation(message, "");
        }

        public void ShowInformation(string message, string caption)
        {
            Action action = () => MB.Show(message, caption, MessageBoxButton.OK, MessageBoxImage.Information);
            Show(action);
        }

        public DialogResponse OpenFile(out string filename, string initDirectory, string fileKinds, IEnumerable<string> extensions)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            string extensionsString;
            if (extensions == null || extensions.Count() == 0)
                extensionsString = "*.*";
            else
                extensionsString = string.Join(";", from e in extensions select "*." + e.TrimStart('.'));
            ofd.Filter = (fileKinds == null ? "" : fileKinds + " ") + "(" + extensionsString + ")|" + extensionsString;
            if (initDirectory != null && Directory.Exists(initDirectory))
                ofd.InitialDirectory = initDirectory;
            ofd.CheckFileExists = true;
            if (ofd.ShowDialog() != true) {
                filename = null;
                return DialogResponse.Cancel;
            }
            filename = ofd.FileName;
            return DialogResponse.Ok;
        }

        public DialogResponse SaveFile(ref string filename, string initDirectory, string fileKinds, IEnumerable<string> extensions)
        {
            SaveFileDialog sfd = new SaveFileDialog();
            string extensionsString;
            if (extensions == null || extensions.Count() == 0)
                extensionsString = "*.*";
            else
                extensionsString = string.Join(";", from e in extensions select "*." + e.TrimStart('.'));
            sfd.Filter = (fileKinds == null ? "" : fileKinds + " ") + "(" + extensionsString + ")|" + extensionsString;
            if (initDirectory != null && Directory.Exists(initDirectory))
                sfd.InitialDirectory = initDirectory;
            sfd.CheckFileExists = false;
            sfd.AddExtension = true;
            sfd.FileName = filename;
            if (sfd.ShowDialog() != true) {
                filename = null;
                return DialogResponse.Cancel;
            }
            filename = sfd.FileName;
            return DialogResponse.Ok;
        }

        public DialogResponse OpenDirectory(out string path, string description, string selectedPath, bool showNewFolderButton = false)
        {    
            System.Windows.Forms.FolderBrowserDialog fbd = new System.Windows.Forms.FolderBrowserDialog();
            fbd.ShowNewFolderButton = showNewFolderButton;
            if (description != null)
                fbd.Description = description;
            if (selectedPath != null)
                fbd.SelectedPath = selectedPath;
            if (fbd.ShowDialog() != System.Windows.Forms.DialogResult.OK) {
                path = null;
                return DialogResponse.Cancel;
            }
            path = fbd.SelectedPath;
            return DialogResponse.Ok;
        }
    }
}
